<template>
  <div v-if="currentUnit && changeToUnit" class="unit-container" @click="handleClick">
    <!-- 旋转背景 -->
    <div class="unit-bg unit-bg-animation-rotate">
      <img src="./images/unit-bg.png" class="unit-bg-image unit-bg-image-animation-scale" />
    </div>

    <!-- 筒条状 -->
    <!-- 固定层 -->
    <div ref="unitBarContainer" class="unit-bar-container unit-bar-all-animation-scale">
      <!-- 抖动层 -->
      <div ref="shakeContainer" class="shake-container">
        <!-- 旋转层 -->
        <img ref="unitBar" src="./images/unit-bar.png" class="unit-bar" />
      </div>

      <img ref="unitBarAll" src="./images/unit-bar-all.png" class="unit-bar-all" />
    </div>

    <!-- 波纹 -->
    <div class="unit-wave-container unit-wave-container-animation">
      <div class="unit-wave wave-animation">
        <Wave v-if="isShowWave" />
      </div>
    </div>

    <!-- 筒列表 -->
    <div class="unit-box">
      <div class="unit-list">
        <div class="unit1 unit1-animation">{{ unitChangeList[0] }}</div>
        <div class="unit2 unit2-animation">{{ unitChangeList[1] }}</div>
        <div class="unit3 opacity0 unit3-animation">{{ unitChangeList[2] }}</div>
      </div>
      <div class="unit unit-transition unit-annimation">筒</div>
    </div>
    <div class="real-unit real-unit-color-animation">
      <div class="unit3">{{ unitMap[currentUnit] }}</div>
      <div class="unit">筒</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { type PropType, type Ref, computed, nextTick, ref, watch } from 'vue'
import Wave from './wave.vue'
import type { UnitType, UnitTypeCN } from './b-multiUnit'

const props = defineProps({
  // 当前筒
  unit: {
    type: String as PropType<UnitTypeCN>,
    default: () => ''
  }
})

defineExpose({
  changeUnit
})

// 当前筒
const currentUnit: Ref<UnitType> = ref('')

// 切成哪个筒
const changeToUnit: Ref<UnitType> = ref('')

const unitMap = {
  LEFT: '左',
  RIGHT: '右',
  DOWN: '下'
}

const unitMapCN = {
  左: 'LEFT',
  右: 'RIGHT',
  下: 'DOWN'
}

watch(
  () => props.unit,
  value => {
    const newValue = value ? (unitMapCN[value as keyof typeof unitMapCN] as UnitType) : 'DOWN'
    if (!currentUnit.value) {
      currentUnit.value = newValue
      changeToUnit.value = newValue
      nextTick(() => {
        if (unitBar.value) {
          const rotateMap = {
            DOWN: 'rotate(0deg)',
            LEFT: 'rotate(120deg)',
            RIGHT: 'rotate(240deg)'
          }
          const rotate = rotateMap[newValue as keyof typeof rotateMap]
          // 让bar对其到对应位置
          if (unitBar.value && unitBarAll.value) {
            unitBar.value.style.transform = rotate
            unitBarAll.value.style.transform = rotate
            setTimeout(() => {
              // 旋转bar
              rotateUnitBar(newValue, newValue)
            }, 50)
          }
        }
      })
    } else {
      changeUnit(value)
    }
  },
  {
    immediate: true
  }
)

const isShowWave = ref(true)

// 筒改变列表
const units = ref({
  DOWN: ['DOWN', 'RIGHT', 'LEFT'],
  LEFT: ['LEFT', 'DOWN', 'RIGHT'],
  RIGHT: ['RIGHT', 'LEFT', 'DOWN']
})

// 筒改变列表-中文
const unitChangeList = computed(() => {
  if (!currentUnit.value || !changeToUnit.value) {
    return []
  }
  return units.value[changeToUnit.value as keyof typeof units.value].map(unit => unitMap[unit as keyof typeof unitMap])
})

// 当前筒
const unitBar = ref(null) as Ref<HTMLElement | null>
// 筒
const unitBarAll = ref(null) as Ref<HTMLElement | null>
// 筒容器
const unitBarContainer = ref(null) as Ref<HTMLElement | null>
// 抖动部分
const shakeContainer = ref(null) as Ref<HTMLElement | null>

/**
 * 旋转 unitBar
 * @param {UnitType} from
 * @param {UnitType} to
 */
function rotateUnitBar(from: UnitType, to: UnitType) {
  // 先移除抖动
  if (shakeContainer.value) {
    shakeContainer.value.classList.remove('shake-animation')
  }
  let barRotated = 0
  if (unitBar.value?.style.transform) {
    // 已经旋转的度数
    barRotated = Number.parseInt(unitBar.value.style.transform.split('rotate(')[1].split('deg')[0])
  }
  // 旋转角度
  const rotationAngle = barRotated + getRotationAngle(from, to)
  // 旋转
  if (unitBar.value && unitBarAll.value) {
    unitBar.value.style.transform = `rotate(${rotationAngle}deg)`
    unitBarAll.value.style.transform = `rotate(${rotationAngle}deg)`
    // 2080ms后开始抖动
    setTimeout(() => {
      if (shakeContainer.value) {
        shakeContainer.value.classList.add('shake-animation')
      }
    }, 2090)
  }
}

/**
 * 获取旋转角度
 * @param {UnitType} from
 * @param {UnitType} to
 */
function getRotationAngle(from: UnitType, to: UnitType) {
  let rotationAngle = 600
  if (from === to) {
    rotationAngle = 360
  } else if ((from === 'DOWN' && to === 'LEFT') || (from === 'LEFT' && to === 'RIGHT') || (from === 'RIGHT' && to === 'DOWN')) {
    rotationAngle = 480
  }
  return rotationAngle
}

function setUnitName(to: UnitType) {
  if (to) {
    changeToUnit.value = to
    // 稍微有个延时变化
    setTimeout(() => {
      currentUnit.value = to
    }, 100)
  }
}

let timer = null as any
// 关闭波纹
function closeWave() {
  if (timer) {
    clearTimeout(timer)
  }
  // 动画时长2880，不关闭会导致波纹不一致
  timer = setTimeout(() => {
    isShowWave.value = false
    timer = null
  }, 2880)
}

/**
 * 切筒
 * @param to 切换到
 */
function changeUnit(to: UnitTypeCN) {
  const changeTo = to ? (unitMapCN[to as keyof typeof unitMapCN] as UnitType) : 'DOWN'
  rotateUnitBar(currentUnit.value, changeTo)
  isShowWave.value = true
  const unitBgDom = document.querySelector('.unit-bg')
  const unitBgImageDom = document.querySelector('.unit-bg-image')
  const waveDom = document.querySelector('.unit-wave')
  const unit1Dom = document.querySelector('.unit1')
  const unit2Dom = document.querySelector('.unit2')
  const unit3Dom = document.querySelector('.unit3')
  const unitTransitionDom = document.querySelector('.unit-transition')
  const realUnitDom = document.querySelector('.real-unit')
  const unitWaveContainerDom = document.querySelector('.unit-wave-container')

  if (!unitBgDom || !unitBgImageDom || !waveDom || !unit1Dom || !unit2Dom || !unit3Dom || !unitTransitionDom || !realUnitDom || !unitWaveContainerDom || !unitBarContainer.value) {
    return
  }

  waveDom.classList.remove('wave-animation')
  unitBgDom.classList.remove('unit-bg-animation-rotate')
  unitBgImageDom.classList.remove('unit-bg-image-animation-scale')
  unit1Dom.classList.remove('unit1-animation')
  unit2Dom.classList.remove('unit2-animation')
  unit3Dom.classList.remove('unit3-animation')
  realUnitDom.classList.remove('real-unit-color-animation')
  unitTransitionDom.classList.remove('unit-annimation')
  unitWaveContainerDom.classList.remove('unit-wave-container-animation')
  unitBarContainer.value.classList.remove('unit-bar-all-animation-scale')
  setTimeout(() => {
    unitBgDom.classList.add('unit-bg-animation-rotate')
    unitBgImageDom.classList.add('unit-bg-image-animation-scale')
    waveDom.classList.add('wave-animation')
    unit1Dom.classList.add('unit1-animation')
    unit2Dom.classList.add('unit2-animation')
    unit3Dom.classList.add('unit3-animation')
    realUnitDom.classList.add('real-unit-color-animation')
    unitTransitionDom.classList.add('unit-annimation')
    unitWaveContainerDom.classList.add('unit-wave-container-animation')
    if (unitBarContainer.value) {
      unitBarContainer.value.classList.add('unit-bar-all-animation-scale')
    }
    closeWave()
    setUnitName(changeTo)
  }, 100)
}

// 点击事件
function handleClick() {
  const unitBgDom = document.querySelector('.unit-bg')
  if (unitBgDom) {
    // 不移除会一直转
    unitBgDom.classList.remove('unit-bg-animation-rotate')
    setTimeout(() => {
      // 新增个动画
      unitBgDom.classList.add('unit-bg-click-animation-rotate')
      setTimeout(() => {
        // 400ms后移除
        unitBgDom.classList.remove('unit-bg-click-animation-rotate')
      }, 420)
    }, 20)
  }
}
</script>

<style scoped lang="less">
@import './b-multiUnit.less';
</style>
